﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;

namespace BaseAttack
{
    public class Unit
    {
        private Canvas UI;
        private Rectangle UnitBody;
        private Point Position;
        private List<Point> Markers = new List<Point>();
        private List<Line> VisiblePath = new List<Line>();

        private Line Weapon;

        public Unit(Canvas UI, Point Position)
        {
            this.UI = UI;
            this.Position = Position;

            // Setup Graphics
            UnitBody = new Rectangle();
            UnitBody.Height = 20;
            UnitBody.Width = 20;
            UnitBody.Fill = Brushes.Green;
            UnitBody.Stroke = Brushes.Black;
            UnitBody.StrokeThickness = 1;
            UnitBody.HorizontalAlignment = HorizontalAlignment.Left;
            UnitBody.VerticalAlignment = VerticalAlignment.Top;
            UI.Children.Add(UnitBody);

            Weapon = new Line();
            Weapon.Visibility = Visibility.Hidden;
            Weapon.Stroke = Brushes.Orange;
            Weapon.StrokeThickness = 2;
            UI.Children.Add(Weapon);

            UpdateGraphics();
        }

        private void UpdateGraphics()
        {
            Canvas.SetTop(UnitBody, Position.Y - (UnitBody.Height / 2));
            Canvas.SetLeft(UnitBody, Position.X - (UnitBody.Width / 2));
        }

        public Boolean HitTest(Point p)
        {
            return (U.Distance(p, Position) < 20);
        }

        public void AddMarker(Point p)
        {
            Markers.Add(p);

            Point prev;
            if (Markers.Count > 1)
                prev = Markers[Markers.Count - 2];
            else
                prev = Position;

            Line l = new Line();
            l.X1 = prev.X;
            l.Y1 = prev.Y;
            l.X2 = p.X;
            l.Y2 = p.Y;

            l.StrokeThickness = 1;
            l.Stroke = Brushes.Blue;
            VisiblePath.Add(l);

            UnitBody.Fill = Brushes.LightGreen;

            UI.Children.Add(l);
        }

        public void CommitMarkers()
        {
            foreach (Line l in VisiblePath)
            {
                l.Stroke = new SolidColorBrush(Color.FromArgb(128, 128, 128, 255));
            }
            UnitBody.Fill = Brushes.Green;
        }


        public void ResetMarkers()
        {
            Markers.Clear();

            foreach (Line l in VisiblePath)
            {
                UI.Children.Remove(l);
            }
            VisiblePath.Clear();
        }

        private Boolean WeaponReady = false;
        private double WeaponCharge = 0;
        public void Tick(double Ticks, List<Target> Targets)
        {
            // Movement
            double DistanceToMove = 1 * Ticks;
            while (Markers.Count > 0)
            {
                Point m = Markers[0];
                if (U.Distance(Position, m) < DistanceToMove)
                {
                    // Move past the marker and keep going
                    DistanceToMove -= U.Distance(Position, m);
                    PopMarker();
                    Position = m;
                }
                else
                {
                    // Move partway to the marker, then stop for now
                    double Total = U.Distance(Position, m);
                    Point UnitVector = new Point((m.X - Position.X) / Total,
                                                  (m.Y - Position.Y) / Total);

                    Position.X += DistanceToMove * UnitVector.X;
                    Position.Y += DistanceToMove * UnitVector.Y;
                    VisiblePath[0].X1 = Position.X;
                    VisiblePath[0].Y1 = Position.Y;
                    break;
                }
            }
            if (Markers.Count > 0)
            {
                UnitBody.LayoutTransform = new RotateTransform(GetAngle(Markers[0], Position));
            }

            // Weapons (pew pew)
            Boolean Firing = false;
            if (WeaponCharge <= 0) WeaponReady = false;
            if (WeaponReady)
            {
                foreach (Target t in Targets)
                {
                    if (t.Alive && U.Distance(t.Center, Position) < 100)
                    {
                        WeaponCharge -= Ticks;
                        Weapon.X1 = Position.X;
                        Weapon.Y1 = Position.Y;
                        Weapon.X2 = t.Center.X;
                        Weapon.Y2 = t.Center.Y;
                        Weapon.Visibility = Visibility.Visible;
                        t.DecreaseHealth(0.05 * Ticks);

                        Firing = true;
                        break;
                    }
                }
            }
            if (!Firing)
            {
                Weapon.Visibility = Visibility.Hidden;
                if (WeaponCharge < 20) WeaponCharge += Ticks;
                else WeaponReady = true;
            }

            // Done
            UpdateGraphics();
        }
        private Point PopMarker()
        {
            Point r = Markers[0];
            Markers.RemoveAt(0);
            UI.Children.Remove(VisiblePath[0]);
            VisiblePath.RemoveAt(0);

            return r;
        }
        private double GetAngle(Point p1, Point p2)
        {
            double xd = p1.X - p2.X;
            double yd = p1.Y - p2.Y;

            if (xd == 0) return 90;
            return Math.Atan(yd / xd) * 180 / Math.PI;
        }

        //--------------------------------Added functions for testing--------------------------------------//

        public double GetVisiblePathLineLength(int index)
        {
            Line l = VisiblePath[index];
            return l.ActualHeight;
        }

        public void SetMarker(Point p)
        {
            Markers.Add(p);
        }

        public Point getPoint
        {
            get { return Position; }
        }

        public List<Line> GetVisiblePath()
        {
            return VisiblePath;
        }

        public List<Point> GetMarkersList()
        {
            return Markers;
        }

        public Rectangle GetUnitBody()
        {
            return UnitBody;
        }

    }
}
